code for initial bringup of secondary VCPUs.
Signed-off-by: Keir Fraser <keir@xensource.com>
#include <xen/interface/physdev.h>
#include <xen/interface/vcpu.h>
+#include <xen/cpu_hotplug.h>
#include <linux/err.h>
EXPORT_SYMBOL(enable_hlt);
/* XXX XEN doesn't use default_idle(), poll_idle(). Use xen_idle() instead. */
-extern void stop_hz_timer(void);
-extern void start_hz_timer(void);
void xen_idle(void)
{
local_irq_disable();
else {
clear_thread_flag(TIF_POLLING_NRFLAG);
smp_mb__after_clear_bit();
- stop_hz_timer();
- /* Blocking includes an implicit local_irq_enable(). */
- HYPERVISOR_block();
- start_hz_timer();
+ safe_halt();
set_thread_flag(TIF_POLLING_NRFLAG);
}
}
cpu_clear(smp_processor_id(), cpu_initialized);
preempt_enable_no_resched();
HYPERVISOR_vcpu_op(VCPUOP_down, smp_processor_id(), NULL);
- /* Same as drivers/xen/core/smpboot.c:cpu_bringup(). */
- cpu_init();
- touch_softlockup_watchdog();
- preempt_disable();
- local_irq_enable();
+ cpu_bringup();
}
#else
static inline void play_dead(void)
* stop_hz_timer / start_hz_timer - enter/exit 'tickless mode' on an idle cpu
* These functions are based on implementations from arch/s390/kernel/time.c
*/
-void stop_hz_timer(void)
+static void stop_hz_timer(void)
{
unsigned int cpu = smp_processor_id();
unsigned long j;
BUG_ON(HYPERVISOR_set_timer_op(jiffies_to_st(j)) != 0);
}
-void start_hz_timer(void)
+static void start_hz_timer(void)
{
cpu_clear(smp_processor_id(), nohz_cpu_mask);
}
+void safe_halt(void)
+{
+ stop_hz_timer();
+ /* Blocking includes an implicit local_irq_enable(). */
+ HYPERVISOR_block();
+ start_hz_timer();
+}
+EXPORT_SYMBOL(safe_halt);
+
+void halt(void)
+{
+ if (irqs_disabled())
+ HYPERVISOR_vcpu_op(VCPUOP_down, smp_processor_id(), NULL);
+}
+EXPORT_SYMBOL(halt);
+
/* No locking required. We are only CPU running, and interrupts are off. */
void time_resume(void)
{
#include <asm/ia32.h>
#include <asm/idle.h>
+#include <xen/cpu_hotplug.h>
+
asmlinkage extern void ret_from_fork(void);
unsigned long kernel_thread_flags = CLONE_VM | CLONE_UNTRACED;
}
/* XXX XEN doesn't use default_idle(), poll_idle(). Use xen_idle() instead. */
-extern void stop_hz_timer(void);
-extern void start_hz_timer(void);
void xen_idle(void)
{
local_irq_disable();
else {
clear_thread_flag(TIF_POLLING_NRFLAG);
smp_mb__after_clear_bit();
- stop_hz_timer();
- /* Blocking includes an implicit local_irq_enable(). */
- HYPERVISOR_block();
- start_hz_timer();
+ safe_halt();
set_thread_flag(TIF_POLLING_NRFLAG);
}
}
cpu_clear(smp_processor_id(), cpu_initialized);
preempt_enable_no_resched();
HYPERVISOR_vcpu_op(VCPUOP_down, smp_processor_id(), NULL);
- /* Same as drivers/xen/core/smpboot.c:cpu_bringup(). */
- cpu_init();
- touch_softlockup_watchdog();
- preempt_disable();
- local_irq_enable();
+ cpu_bringup();
}
#else
static inline void play_dead(void)
}
#endif
-static void cpu_bringup(void)
+void cpu_bringup(void)
{
cpu_init();
touch_softlockup_watchdog();
preempt_disable();
local_irq_enable();
+}
+
+static void cpu_bringup_and_idle(void)
+{
+ cpu_bringup();
cpu_idle();
}
ctxt.user_regs.fs = 0;
ctxt.user_regs.gs = 0;
ctxt.user_regs.ss = __KERNEL_DS;
- ctxt.user_regs.eip = (unsigned long)cpu_bringup;
+ ctxt.user_regs.eip = (unsigned long)cpu_bringup_and_idle;
ctxt.user_regs.eflags = X86_EFLAGS_IF | 0x1000; /* IOPL_RING1 */
memset(&ctxt.fpu_ctxt, 0, sizeof(ctxt.fpu_ctxt));
preempt_enable_no_resched(); \
} while (0)
-#define safe_halt() ((void)0)
-#define halt() ((void)0)
+void safe_halt(void);
+void halt(void);
#define __save_and_cli(x) \
do { \
preempt_enable_no_resched(); \
___x; })
-#define safe_halt() ((void)0)
-#define halt() ((void)0)
+void safe_halt(void);
+void halt(void);
void cpu_idle_wait(void);
int smp_suspend(void);
void smp_resume(void);
+void cpu_bringup(void);
+
#else /* !defined(CONFIG_HOTPLUG_CPU) */
#define cpu_up_check(cpu) (0)